#include "stdio.h"
#include "microCPU.h"
#include "microTime.h"
#include "microList.h"
#include "microMemory.h"
#include "microDelay.h"
#include "microTask.h"
#include "microTimer.h"


/* 定时器链表 */
MrListType g_typeMrListTimer = {&g_typeMrListTimer, &g_typeMrListTimer};


int8_t cMrTimerCreate(MrTimerType **pptypeTimerHandle, vMrTimerFunction pvTaskFunction, uint32_t uiParameters, int64_t lTick)
{
    MrTimerType *ptypeTimerHandle = NULL;

    if(pvTaskFunction == NULL)
        return 1;

    /* 申请定时器控制块 */
    if((ptypeTimerHandle = pvMrMemoryCalloc(1, sizeof(MrTimerType))) == NULL)
        return 2;

    cMrListInit(&ptypeTimerHandle->list, 0);
    ptypeTimerHandle->list.pElement = ptypeTimerHandle;
    ptypeTimerHandle->pFunction     = pvTaskFunction;
    ptypeTimerHandle->parameters    = uiParameters;
    ptypeTimerHandle->duration      = lTick;

    if(pptypeTimerHandle != NULL)
        *pptypeTimerHandle = ptypeTimerHandle;

    return 0;
}

/* 启动定时器 */
int8_t cMrTimerStart(MrTimerType *ptypeTimerHandle, MrTimerStateEnum enumState, int64_t lTick)
{
    if(ptypeTimerHandle == NULL)
        return 1;

    ptypeTimerHandle->state         = enumState;
    ptypeTimerHandle->duration      = lTick;
    ptypeTimerHandle->list.value    = lMrTickGet();
    ptypeTimerHandle->list.value   += (ptypeTimerHandle->state & MrTimerImmediately) ? 0 : ptypeTimerHandle->duration;

    /* 进入临界段 */
    vMrCpuDisableIsr();

    /* 从当前链表中移除 */
    cMrListRemove(&ptypeTimerHandle->list);

    /* 插入到定时器链表 */
    cMrListInsert(&g_typeMrListTimer, &ptypeTimerHandle->list);

    /* 退出临界段 */
    vMrCpuEnableIsr();

    /* 触发定时器任务执行一次 */
    cMrTaskResume(g_ptypeMrTaskTimerHandle);

    return 0;
}

/* 停止定时器 */
int8_t cMrTimerStop(MrTimerType *ptypeTimerHandle)
{
    if(ptypeTimerHandle == NULL)
        return 1;

    /* 进入临界段 */
    vMrCpuDisableIsr();

    /* 从当前链表中移除 */
    cMrListRemove(&ptypeTimerHandle->list);

    ptypeTimerHandle->state = MrTimerStop;

    /* 退出临界段 */
    vMrCpuEnableIsr();

    return 0;
}

/* 定时器溢出检查任务 */
void vMrTaskTimer(uint32_t uiParameters)
{
    MrListType *ptypeListNow = NULL;
    MrTimerType *ptypeTimerNow = NULL;
    int64_t lTick = 0;

    while(1)
    {
        /* 把遍历指针指向就绪链表首部 */
        while((ptypeListNow = g_typeMrListTimer.pNext) != &g_typeMrListTimer)
        {
            lTick = lMrTickGet();

            /* 排序存储，第一个不满足，后面的也不会满足 */
            if(lTick < ptypeListNow->value)
                break;

            /* 进入临界段 */
            vMrCpuDisableIsr();

            /* 从定时器链表中移除 */
            cMrListRemove(ptypeListNow);

            /* 退出临界段 */
            vMrCpuEnableIsr();

            ptypeTimerNow = (MrTimerType *)ptypeListNow->pElement;

            /* 执行回调函数 */
            ptypeTimerNow->pFunction(ptypeTimerNow->parameters);

            /* 循环计时 */
            if(ptypeTimerNow->state & MrTimerCirculation)
            {
                ptypeListNow->value += ptypeTimerNow->duration;

                /* 进入临界段 */
                vMrCpuDisableIsr();

                /* 重新插入到定时器链表 */
                cMrListInsert(&g_typeMrListTimer, ptypeListNow);

                /* 退出临界段 */
                vMrCpuEnableIsr();
            }
        }

        /* 下次定时器溢出还需要的 tick 数量 */
        lTick = g_typeMrListTimer.pNext->value - lMrTickGet();

        vMrDelayTick(NULL, lTick);
    }
}
